<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手写一个防抖函数</title>
    <style>
        body{
            height: 2000px;
        }
    </style>
</head>

<body>
    <script>
        /*防抖，即 短时间内大量触发同一事件，只会执行一次函数 ，
        实现原理为 设置一个定时器，约定在 xx 毫秒后再触发事件处理
        ，每次触发事件都会重新设置计时器，直到 xx 毫秒内无第二次操作 ，
        防抖常用于搜索框/滚动条的监听事件处理，如果不做防抖，每输入一个字/滚动屏幕，
        都会触发事件处理，造成性能浪费。
        */
        // 让输入完毕后过wait再查询（延迟执行）
        function debounce1(func, wait) {
            let timeout = null
            return function () {
                let context = this;
                let args = arguments;
                if (timeout) {
                    clearInterval(timeout)
                }
                timeout = setTimeout(() => {
                    func.apply(context, args);
                }, wait);
            }
        }
        // 让输入完成立即查询，过wait秒才能再查询（立即执行）
        function debounce2(func, wait) {
            let timeout = null;
            return function () {
                let context = this;
                let args = arguments;
                if (timeout) {
                    clearTimeout(timeout)
                }
                let callNow = !timeout;
                timeout = setTimeout(() => {
                    timeout = null
                }, wait);
                if (callNow) {
                    func.apply(context, args);
                }
            }
        }

        function fn() {
            console.log("开始了吗");
        }
       
        /*
        手写一个节流函数
        防抖是 延迟执行 ，而节流是 间隔执行 ，函数节流即 每隔一段时间就执行一次 ，
        实现原理为 设置一个定时器，约定 xx 毫秒后执行事件，
        如果时间到了，那么执行函数并重置定时器 ，和防抖的区别在于，
        防抖每次触发事件都重置定时器，而节流在定时器到时间后再清空定时器
        */
        function throttle1(func, wait) {
            let timeout = null
            return function () {
                let context = this
                let args = arguments
                if (!timeout) {
                    timeout = setTimeout(() => {
                        timeout = null
                        func.apply(context, args)
                    }, wait)
                }
            }
        }

        function throttle2(func, wait) {
            var prev = 0;
            return function () {
                let now = Date.now();
                let context = this;
                let args = arguments;
                if (now - prev > wait) {
                    func.apply(context, args);
                    prev = now;
                }
            }
        }
        /*
         * 解决第一次调用时不立即执行，最后一次调用时，不用等xx秒后再执行
         * 
         */
        function throttle3(fn, delay) {
            let timer = null;
            let startTime = Date.now();
            return function () {
                let currentTime = Date.now();
                let remaining = delay - (currentTime - startTime);
                let context = this;
                let args = arguments;
                if (remaining <= 0) {
                    fn.apply(context, args);
                    startTime = currentTime;
                } else {
                    timer = setTimeout(fn, remaining);
                }
            }
        }
        window.onscroll = throttle2(fn, 3000);
    </script>
</body>

</html>